package ling.archives.service;


import com.easy.query.core.proxy.core.draft.Draft3;
import com.easy.query.core.proxy.sql.Select;
import com.ruoyi.common.utils.StringUtils;
import io.lettuce.core.KeyValue;
import ling.archives.common.DataUtil;
import ling.archives.common.EQueryService;
import ling.archives.common.domain.Result;
import ling.archives.domain.ApprovalRecord;
import ling.archives.domain.Archive;
import ling.archives.domain.ArchiveContent;
import ling.archives.domain.DocumentClass;
import ling.archives.domain.dto.ArchiveContentXls;
import ling.archives.domain.dto.ArchiveXls;
import lombok.SneakyThrows;
import lombok.var;
import net.sourceforge.pinyin4j.PinyinHelper;

import net.sourceforge.pinyin4j.format.*;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.io.File;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class ArchiveService extends EQueryService<Archive> {
    @Transactional
    public Result importToTab(List<ArchiveXls> archives, List<ArchiveContentXls> contents,Long documnetClassId) {
        //格式检查：自洽性
        //数据库重复检查
        //物理文件检查
        var arList = archives.stream().map(ArchiveXls::toEntity).collect(Collectors.toList());
        var contList = contents.stream().map(ArchiveContentXls::toEntity).collect(Collectors.toList());

        var surplus = new ArrayList<ArchiveContent>();
        contList.forEach(p -> {
            p.setHeadPy(gainHeadComb(p.getHouseholdHead()));
            var reTmp = arList.stream().filter(x -> Objects.equals(x.getFullNum(), p.getArchiveNum())).findFirst();
            if (reTmp.isPresent()) {
                p.setArchive(reTmp.get());
                reTmp.get().getContents().add(p);
            } else surplus.add(p);
        });
        if (!surplus.isEmpty()) {
            var numTmps = surplus.stream().map(ArchiveContent::getFullNum).collect(Collectors.toList());
            return Result.bad("页数据与案卷数据不对应：" + String.join(",", numTmps)); //有未匹配
        }
//        contList.forEach(p -> {
//            p.setHeadPy(gainHeadComb(p.getHouseholdHead()));
//            var reTmp = arList.stream().filter(x -> Objects.equals(x.getNum(), p.getNum())).findFirst();
//            if (reTmp.isPresent()) {
//                p.setArchive(reTmp.get());
//                reTmp.get().getContents().add(p);
//            }
//        });
        var arNums = arList.stream().map(Archive::getFullNum).collect(Collectors.toList());
        var repeat = queryHelper.entityQuery(Archive.class).where(p -> p.fullNum().in(arNums)).select(p -> p.fullNum()).toList();//
        if (!repeat.isEmpty()) {
            return Result.bad("档号已存在：" + String.join(",", repeat));//重复
        }
        //路径设置
        var docc=queryHelper.queryable(DocumentClass.class).whereById(documnetClassId).firstOrNull();
        if(docc==null)
            return Result.bad("分类不能为空");
        var doccPath=docc.gianFullPath();
        arList.forEach(p->{
            p.setDoccId(documnetClassId);
            p.setDoccPath(doccPath);
            p.setFilePath(gainFileDirPath(p,docc.getDirPath()));
            restContentFilesPath(p);
        });
        // 保存档案数据
        saveArchive(arList, contList);
        doccSet(arList.toArray(new Archive[0]));

        // 手动获取刚保存的档案ID列表
        List<Long> savedIds = arList.stream()
                .map(Archive::getId)
                .filter(Objects::nonNull)
                .collect(Collectors.toList());
        
        // 重新从数据库查询以确保获取最新状态
        var savedArchives = queryHelper.entityQuery(Archive.class)
                .where(p -> p.id().in(savedIds))
                .toList();
                
        if (!savedArchives.isEmpty()) {
            // 为每个档案创建独立的审批记录
            for (Archive archive : savedArchives) {
                // 创建审批工作流
                var approvalResult = approvalService.createWF(
                    ApprovalTmplName,
                    "归档申请:" + archive.getTitle(),
                    DataUtil.toJson(new Long[]{archive.getId()}),
                    "档案导入自动归档申请"
                );
                
                if (approvalResult.isSuccess()) {
                    // 更新档案的审批ID和锁定状态
                    archive.setApprovalId(approvalResult.getData().intValue());
                    archive.setApprovalLock("1");
                    queryHelper.entityQuery().updatable(archive).executeRows();
                }
            }
        }
        
        return Result.ok();
    }
      void restContentFilesPath(Archive archive) {
          archive.getContents().forEach(p -> {
              var pathJson = ArchiveContent.gainFilesPathJson(p, archive.getFilePath());
              p.setPageFiles(pathJson);
          });
      }
    @Transactional
    public void saveArchive(List<Archive> arList, List<ArchiveContent> contList) {
        queryHelper.entityQuery().insertable(arList).executeRows(true);
        arList.forEach(p -> p.getContents().forEach(x -> x.setArchiveId(p.getId())));
        queryHelper.entityQuery().insertable(contList).executeRows();
    }
    public static  final String ContentFileBasePath="ar_data/";
    /** 分类列表
     *
     * @return
     */
    public List<DocumentClass> DoccTypeList(){
        return queryHelper.entityQuery(DocumentClass.class).where(d -> d.type().eq(0)).toList();
    }
    /** 存档，检查
     *
     * @param ids 档案皮id
     * @return
     */
    @Transactional
    public Result<List<String>> filing(Long[] ids,String remark) {
        var arList = queryHelper.entityQuery(Archive.class)
                .where(p -> {
                    p.id().in(ids);
                    // 新导入的档案状态和审批锁都是默认值，所以不需要检查
                    // p.status().eq("0");
                    // p.approvalLock().eq("0");
                }).toList();
        if (arList.size() != ids.length)
            return Result.bad("数据不正确");
        //文件检查
        var list = queryHelper.entityQuery(ArchiveContent.class).where(a -> a.archiveId().in(ids)).toList();
        var baseDir = ContentFileBasePath;
        //物理文件存在检查
//        var msgList = list.stream().map(p -> fileExist(p,baseDir)).filter(p -> !p.isSuccess()).map(p -> p.getData()).collect(Collectors.toList());
//        if (!msgList.isEmpty())
//            return Result.bad("部分文件不存在", msgList);
        //
        approvalService.createWF(ApprovalTmplName, "归档申请:" + arList.get(0).getTitle(), DataUtil.toJson(ids), remark);
        arList.forEach(p -> {
            p.setApprovalLock("1");
        });
        queryHelper.entityQuery().updatable(arList).executeRows();
//        var arList = queryHelper.entityQuery(Archive.class).where(a -> a.id().in(ids)).toList();
//        arList.forEach(p -> p.setStatus("1"));
//        queryHelper.entityQuery().updatable(arList).executeRows();
        return Result.ok();
    }
   public static final String ApprovalTmplName="ar_wf_filing" ;
    @Resource
    ApprovalService approvalService;
    public Result<String> filingApproval(Long nodeId, boolean isPass, String remark){
            var status=approvalService.Approval(nodeId,isPass,remark);
            if(Objects.equals(status.getData().getStatus(), ApprovalRecord.StatusPass))
            {
                var ids=DataUtil.toObjByJson(status.getData().getFormData(),Long[].class);
                var arList = queryHelper.entityQuery(Archive.class).where(a -> a.id().in(ids)).toList();
                arList.forEach(p -> {
                    p.setStatus("1");
                    p.setApprovalLock("0");
                });
                queryHelper.entityQuery().updatable(arList).executeRows();
            }
            else if(Objects.equals(status.getData().getStatus(), ApprovalRecord.StatusReject)) {
                var ids = DataUtil.toObjByJson(status.getData().getFormData(), Long[].class);
                var arList = queryHelper.entityQuery(Archive.class).where(a -> a.id().in(ids)).toList();
                arList.forEach(p -> {
                    p.setStatus("3");
                    p.setApprovalLock("0");
                });
                queryHelper.entityQuery().updatable(arList).executeRows();
            }
            return Result.ok(status.getData().getStatus());
    }

    String fileBasePath = "";


    private static void filesPathSet(ArchiveContent content,String dirPath) {
        if(content.getPageCount() ==1)
        {
            var pathStr= content.getFullNum()+".tif";
            content.setPageFiles(DataUtil.toJson(new String[]{pathStr}));

        }else {
            var pathArr = new ArrayList<String>();
            for (int i = 1; i <= content.getPageCount(); i++) {
                pathArr.add(content.getFullNum() +"-"+i +".tif");
            }
            content.setPageFiles(DataUtil.toJson(pathArr));
        }
    }
     String gainFileDirPath(Archive ar,String basePath) {
        //\1宅基地使用证存根\1990年度\0002-纸房乡1990年度001-541号
        if (basePath == null) {
            basePath = "";
        }
        if (basePath.endsWith("\\")) {
            return basePath + ar.getYear() + "年度\\" + ar.getFilePath();
        } else {
            return basePath + (basePath.isEmpty() ? "" : "\\") + ar.getYear() + "年度\\" + ar.getFilePath();
        }
    }


    /**
     * 文件存在性验证
     *
     * @param arc
     * @return
     */
    @SneakyThrows
    public Result<String> fileExist(ArchiveContent arc,String dirPath) {
        var paths = arc.getPageFiles();

        var strArr = DataUtil.toObjByJson(paths, String[].class);
        StringBuilder msgs = new StringBuilder();
        for (var item : strArr) {
            File file = new File(dirPath + item);
            if (!file.exists() || !file.isFile()) {
                msgs.append(item).append(";");
            }
        }
        var msg = msgs.toString();
        if (StringUtils.isBlank(msg))
            return Result.ok();
        else
            return Result.bad("文件不存在", msg);
    }

    public List<Draft3<Long, Integer, String>> doccSet(Archive[] entitys) {
        var list = Arrays.stream(entitys).map(a -> {
            var tmp = new Draft3<Long, Integer, String>();
            tmp.setValue1(a.getDoccId());
            tmp.setValue2(a.getYear());
            tmp.setValue3(a.getTownName());
            return tmp;
        }).collect(Collectors.toList());
        return doccSet(list);
    }
    /** 统计当前目录结构,按数据库数据
     *
     * @param dto
     * @return
     */
    @Transactional
   public List<Draft3<Long, Integer, String>> doccSet(Archive dto) {
       //按条件进行统计，然后与现有对比：年、乡镇，没有则添加
       var list = queryHelper.entityQuery(Archive.class)
               .whereObject(dto).select(a -> Select.DRAFT.of(a.doccId(), a.year(), a.townName()))
               .distinct().toList();
        return doccSet(list);
    }

    private List<Draft3<Long, Integer, String>> doccSet(List<Draft3<Long, Integer, String>> list) {
        var yearList = list.stream().map(p -> p.getValue2() + "").distinct().collect(Collectors.toList());
        var doccList = queryHelper.entityQuery(DocumentClass.class)
                .where(d -> d.val().in(yearList))
                .asTreeCTE()
                .toTreeList();
        var missYear = new ArrayList<Draft3<Long, Integer, String>>();
        var missTown = new ArrayList<KeyValue<DocumentClass, Draft3<Long, Integer, String>>>();
        list.forEach(p -> {
            var tmpList = doccList.stream()
                    .filter(x -> Objects.equals(x.getParentId(), p.getValue1()) && Objects.equals(x.getVal(), p.getValue2() + ""))
                    .collect(Collectors.toList());
            if (tmpList.isEmpty())
                missYear.add(p);
            else {
                var townRe = tmpList.get(0).getChildren().stream().filter(x -> Objects.equals(x.getVal(), p.getValue3())).collect(Collectors.toList());
                if (townRe.isEmpty())
                    missTown.add(KeyValue.fromNullable(tmpList.get(0), p));
            }
        });
        var yearNewList = new ArrayList<DocumentClass>();
        var nowDate=new Date();
        missYear.forEach(p -> {
            var item = new DocumentClass();
            var tmp = yearNewList.stream().filter(x -> Objects.equals(x.getVal(), p.getValue2() + "") && Objects.equals(x.getParentId(), p.getValue1()))
                    .findFirst();
            if (tmp.isPresent()) {
                item = tmp.get();
            } else {
                item.setTitle(p.getValue2() + "年");
                item.setVal(p.getValue2() + "");
                item.setType(1);
                item.setParentId(p.getValue1());
                item.setUpdatedTime(nowDate);
                yearNewList.add(item);
            }
            if (p.getValue3() != null) {
                var child = new DocumentClass();
                child.setTitle(p.getValue3());
                child.setVal(p.getValue3());
                child.setType(1);
                child.setUpdatedTime(nowDate);
                item.getChildren().add(child);
            }
        });
        var townNewList = missTown.stream()
            .filter(p -> p.getValue() != null && p.getValue().getValue3() != null)
            .map(p -> {
                var item = new DocumentClass();
                item.setType(1);
                item.setTitle(p.getValue().getValue3());
                item.setVal(item.getTitle());
                item.setParentId(p.getKey().getId());
                item.setUpdatedTime(nowDate);
                return item;
            }).collect(Collectors.toList());
        queryHelper.entityQuery().insertable(yearNewList).executeRows(true);
        var childList = yearNewList.stream().flatMap(p -> p.getChildren().stream().map(x->{
            x.setParentId(p.getId());
            return x;
        })).collect(Collectors.toList());
        childList.addAll(townNewList);
        
        // 根据val值去重
        var uniqueList = childList.stream()
            .collect(Collectors.toMap(
                DocumentClass::getVal,
                x -> x,
                (x1, x2) -> x1
            ))
            .values()
            .stream()
            .collect(Collectors.toList());
            
        queryHelper.entityQuery().insertable(uniqueList).executeRows();
        return list;
    }

    @SneakyThrows
    public String gainHeadComb(String hz){
        HanyuPinyinOutputFormat outputFormat = new HanyuPinyinOutputFormat();
        outputFormat.setToneType(HanyuPinyinToneType.WITHOUT_TONE);
        outputFormat.setCaseType(HanyuPinyinCaseType.LOWERCASE);
        outputFormat.setVCharType(HanyuPinyinVCharType.WITH_V);
        List<List<String>> list=new ArrayList<List<String>>();
        List<List<String>> listPy=new ArrayList<List<String>>();
        for (var item :hz.toCharArray()) {
            var pins = PinyinHelper.toHanyuPinyinStringArray(item, outputFormat);
            var heads= Arrays.stream(pins).map(p -> p.charAt(0)+"").distinct().collect(Collectors.toList());
            list.add(heads);
            listPy.add(Arrays.asList(pins));

        }
        var re=innerJoin(list.toArray(new List[0]));
        var re2=innerJoin(listPy.toArray(new List[0]));
        re.addAll(re2);
        return String.join(",",re);
    }
    public  List<String> innerJoin(List<String>... lists){
        var list1 = lists[0].stream().distinct().collect(Collectors.toList());
        for (int i = 0; i < lists.length-1; i++) {
            var list2 = lists[i + 1];
            List<String> finalList = list1;
            list1= list2.stream().flatMap(p -> finalList.stream().map(x -> x+p)).collect(Collectors.toList());
        }
        return list1.stream().distinct().collect(Collectors.toList());
    }
}
